package com.object.aop;

import com.object.aop.transaction.LqTransaction;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;

import javax.annotation.Resource;
import java.lang.reflect.Method;

/**
 * 自定义事务注解     核心实现类
 */
@Configuration
@Slf4j
@Aspect  //切面类
//@Scope("prototype") // 设置成原型解决线程安全 多例模式
public class StartLqTransaction {

    @Pointcut("execution(public * com.object.module.*.*.*.*.*.*(..))")
    public void log() {
    }

    //获取事务源
    @Resource
    private DataSourceTransactionManager dataSourceTransactionManager;


    @Around("log()")
    public Object around(ProceedingJoinPoint joinPoint) {
        //  "前置通知"
        Object proceed = null;
        TransactionStatus status = null;
        try {
            //获取代理对象的方法
            String name = joinPoint.getSignature().getName();
            //获取目标对象
            Class<?> aClass = joinPoint.getTarget().getClass();
            //获取对象类型
            Class<?>[] par = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
            //获取目标对象的方法
            Method method = aClass.getMethod(name, par);

            LqTransaction lqTransactions = method.getDeclaredAnnotation(LqTransaction.class);
            if (lqTransactions != null) {
                //开启事务
                log.info("开启事务 执行方法:" + name);
                status = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
            }
            //调用代理目标对象
            proceed = joinPoint.proceed();
            if (status != null) {
                //提交事务
                log.info("提交事务 执行方法:" + name);
                dataSourceTransactionManager.commit(status);
            }
            // 后值通知
        } catch (Throwable throwable) {
            //异常通知
            //回滚事务
            log.info("回滚事务  异常:" + throwable);
            throwable.printStackTrace();
            dataSourceTransactionManager.rollback(status);
        }
        return proceed;

    }
}

